package com.mashibing.apipassenger.service;

import com.mashibing.apipassenger.remote.ServicePassengerUserClient;
import com.mashibing.apipassenger.remote.ServiceVerificationcodeClient;
import com.mashibing.internalcommon.constant.CommonStatusEnum;
import com.mashibing.internalcommon.constant.IdentityConstants;
import com.mashibing.internalcommon.constant.TokenConstants;
import com.mashibing.internalcommon.dto.ResponseResult;
import com.mashibing.internalcommon.reponse.NumberCodeResponse;
import com.mashibing.internalcommon.reponse.TokenResponse;
import com.mashibing.internalcommon.request.VerificationCodeDTO;
import com.mashibing.internalcommon.util.JwtUtils;
import com.mashibing.internalcommon.util.RedisPrefixUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.core.RedisOperations;
import org.springframework.data.redis.core.SessionCallback;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.util.concurrent.TimeUnit;

import java.util.concurrent.TimeUnit;

@Service
public class VerificationCodeService {

    @Autowired
    private ServiceVerificationcodeClient serviceVerificationcodeClient;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    private ServicePassengerUserClient servicePassengerUserClient;

    /**
     * 生成验证码
     * @param passengerPhone 手机号
     * @return
     */
    public ResponseResult generatorCode(String passengerPhone) {

        String tag = "num";
        if (passengerPhone.endsWith("6")){
            tag = "str";
        }

        //调用验证码服务，获取验证码
        ResponseResult<NumberCodeResponse> numberCodeResponse = serviceVerificationcodeClient.getNumberCode(6,tag);
        String numberCode = numberCodeResponse.getData().getNumberCode();

        System.out.println("api-passenger的手机号："+ passengerPhone + "收到的验证码："+numberCode);

        //存入redis
        //key,value,过期时间
        String key = RedisPrefixUtils.generatorByPhone(passengerPhone,IdentityConstants.PASSENGER_IDENTITY);
        //存入redis
        stringRedisTemplate.opsForValue().set(key,numberCode+"",2, TimeUnit.MINUTES);

        //通过短信服务商，将对应的验证码发送到手机上，阿里短信服务、腾讯短讯通、华信、容联
        return ResponseResult.success("");
    }

    /**
     * 校验验证码
     * @param passengerPhone 手机号
     * @param verificationCode 验证码
     * @return
     */
    public ResponseResult checkCode(String passengerPhone , String verificationCode) {
        //根据手机号，去redis读取验证码
        //生成key
        String key = RedisPrefixUtils.generatorByPhone(passengerPhone,IdentityConstants.PASSENGER_IDENTITY);
        //根据key获取value
        String codeRedis = stringRedisTemplate.opsForValue().get(key);
        System.out.println("redis中的value:"+codeRedis);

        //校验验证码
        if(StringUtils.isBlank(codeRedis)){
            return ResponseResult.fail(CommonStatusEnum.VERIFICATION_CODE_ERROR.getCode(),CommonStatusEnum.VERIFICATION_CODE_ERROR.getValue());
        }
        if(!verificationCode.trim().equals(codeRedis.trim())){
            return ResponseResult.fail(CommonStatusEnum.VERIFICATION_CODE_ERROR.getCode(),CommonStatusEnum.VERIFICATION_CODE_ERROR.getValue());
        }

        //判断原来是否有用户，并进行对应的处理
        VerificationCodeDTO verificationCodeDTO = new VerificationCodeDTO();
        verificationCodeDTO.setPassengerPhone(passengerPhone);
        try{
            servicePassengerUserClient.loginOrRegister(verificationCodeDTO);
        }catch (RuntimeException e){
            return ResponseResult.fail(CommonStatusEnum.CALL_USER_ADD_ERROR.getCode(),CommonStatusEnum.CALL_USER_ADD_ERROR.getValue());
        }
        //颁发令牌，不应该用魔法值，用常量
        String accessToken = JwtUtils.generatorToken(passengerPhone, IdentityConstants.PASSENGER_IDENTITY, TokenConstants.ACCESS_TOKEN_TYPE);
        String refreshToken = JwtUtils.generatorToken(passengerPhone, IdentityConstants.PASSENGER_IDENTITY,TokenConstants.REFRESH_TOKEN_TYPE);

        //开启redis事务支持
        stringRedisTemplate.setEnableTransactionSupport(true);
        SessionCallback<Boolean> callback = new SessionCallback<Boolean>() {
            @Override
            public Boolean execute(RedisOperations operations) throws DataAccessException {
                //事务开始
                stringRedisTemplate.multi();
                try{
                    //将token存到redis
                    String accessTokenKey = RedisPrefixUtils.generatorTokenKey(passengerPhone, IdentityConstants.PASSENGER_IDENTITY,TokenConstants.ACCESS_TOKEN_TYPE);
                    operations.opsForValue().set(accessTokenKey,accessToken,30,TimeUnit.DAYS);
                    String refreshTokenKey = RedisPrefixUtils.generatorTokenKey(passengerPhone, IdentityConstants.PASSENGER_IDENTITY,TokenConstants.REFRESH_TOKEN_TYPE);
                    operations.opsForValue().set(refreshTokenKey,refreshToken,31,TimeUnit.DAYS);
                    operations.exec();
                    return true;
                }catch(Exception e){
                    operations.discard();
                    return false;
                }
            }
        };
        Boolean execute = stringRedisTemplate.execute(callback);
        System.out.println("事务提交or回滚："+execute);
        if(execute){
            //响应
            TokenResponse tokenResponse = new TokenResponse();
            tokenResponse.setAccessToken(accessToken);
            tokenResponse.setRefreshToken(refreshToken);
            return ResponseResult.success(tokenResponse);
        }else{
            return ResponseResult.fail(CommonStatusEnum.CHECK_CODE_ERROR.getCode(),CommonStatusEnum.CHECK_CODE_ERROR.getValue());
        }


    }

}
